package com.itheima.d6_map_impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

/**
 * 目标：掌握Map集合下的实现类：HashMap集合的底层原理。
 *      HashMap跟HashSet的底层原理是一模一样的，都是基于哈希表实现的。
 *
 *      实际上：原来学的Set系列集合的底层就是基于Map实现的，只是Set集合中的元素只要键数据，不要值数据而已。
 *
 *      哈希表
 * JDK8之前，哈希表 = 数组+链表
 * JDK8开始，哈希表 = 数组+链表+红黑树
 * 哈希表是一种增删改查数据，性能都较好的数据结构。
 *
 *  HashMap的底层原理:
 *          利用键计算哈希值，跟值无关
 *
 *  JDK8开始:
 *          哈希值相同的元素形成的链表长度超过8 & 数组扩容，数组长度>=64，链表自动转成红黑树
 *
 * HashMap集合是一种增删改查数据，性能都较好的集合
 * 但是它是无序，不能重复，没有索引支持的（由键决定特点）
 * HashMap的键依赖hashCode方法和equals方法保证键的唯一
 * 如果键存储的是自定义类型的对象，可以通过重写hashCode和equals方法，这样可以保证多个对象内容一样时，HashMap集合就能认为是重复的。
 *          通过hashcode方法计算哈希值，也就是在数组中的索引，如果该索引处有其他的元素，就要用equals方法进行比较是否重复
 *
 */
public class Test1HashMap {
    public static void main(String[] args) {

        /**
         * hashSet底层源码：
         * public HashSet() {
         *         map = new HashMap<>();
         *     }
         */
        new HashSet<>();

        /*
        HashMap底层原理：
            第一次添加数据的时候，也是会初始化一个长度16的数组，然后把一组键值对作为一个entry对象放入数组中，
            利用键计算哈希值，跟值无关
            jdk8之前：如果此时还有其他的元素求得的哈希值与老元素是同一个哈希值，那么把新元素放在数组中，老元素挂在新元素下面作为链表
            jdk8之后：会把新元素放在老元素的下方作为链表

         */
        Map<Student, String> map = new HashMap<>();
        map.put(new Student("蜘蛛精", 25, 168.5), "盘丝洞");
        map.put(new Student("蜘蛛精", 25, 168.5), "水帘洞");
        map.put(new Student("至尊宝", 23, 163.5), "水帘洞");
        map.put(new Student("牛魔王", 28, 183.5), "牛头山");
        map.put(new Student("曾季洪", 25, 168),"江西");
        System.out.println(map);
    }
}
